Skip to content

feat(AI-011): bootstrap opencode + canonical AGENTS.md migration#34

Merged
mlorentedev merged 2 commits into
mainfrom
feat/AI-011-opencode-bootstrap
May 17, 2026
Merged

feat(AI-011): bootstrap opencode + canonical AGENTS.md migration#34
mlorentedev merged 2 commits into
mainfrom
feat/AI-011-opencode-bootstrap

Conversation

@mlorentedev
Copy link
Copy Markdown
Owner

Summary

Bootstraps OpenCode as a secondary AI coding agent alongside Claude Code, with the Go subscription ($10/mo fixed) as the primary provider — catalog-restricted to DeepSeek V4 Pro + Kimi K2.6 to prevent accidental PAYG billing on Zen frontier models. OpenRouter added as an env-detected fallback (reuses existing OPENROUTER_API_KEY). Aider stays in this PR for coexistence; sunset lands in a follow-up PR.

Folds in AI-013 (copilot-instructions-refresh): per ADR-009, the canonical agent instructions move to AGENTS.md at repo root (read natively by OpenCode and other agents.md-aware tools). ai/claude/CLAUDE.md, ai/gemini/GEMINI.md, and both copilot-instructions.md files shrink to pointer-style files retaining only agent-specific extensions.

Bug fixes en passant (zero-debt rule):

  • Unresolved template placeholder `the knowledge base (...)` in both copilot-instructions.md files.
  • Wrong path %USERPROFILE%\Apps\knowledge\Projects\knowledge.

Idempotence (per pattern-setup-script-idempotence)

  • command -v opencode gate before install (no force re-install).
  • cmp -s reconcile-not-skip on config deploy.
  • Post-deploy assertion: binary reachable + version reports.
  • No new silenced errors (2>/dev/null || true).
  • PATH addition via ensure_line_in_file (idempotent, no manual sed).

Three-layer PAYG guardrail

Layer Where What it does
1. Config opencode.jsonc provider.opencode-go.models lists only Go catalog; /models picker hides frontier.
2. Workspace Zen dashboard Set PAYG cap to $0 (documented in runbook).
3. Payment Zen dashboard No payment method for PAYG → frontier calls fail rather than charge.

Tests

  • 27 new in tests/opencode.bats — relational (not presence-only): idempotence pattern, reconcile-not-skip, regression test for aider coexistence, schema declaration, MCP mirror, model restriction, pointer-file enforcement on CLAUDE.md/GEMINI.md/copilot.
  • healthcheck.sh extended with section 10/11 (OpenCode binary + config + schema).
  • healthcheck.bats updated for 11-section count + renamed assertions.
  • 493/493 tests pass. ShellCheck clean (one info-level SC2016 suppressed with justification).

Test plan

  • Clean-install: `./setup-linux.sh` on a fresh box → `command -v opencode` resolves, `opencode --version` reports.
  • Idempotence: re-run `./setup-linux.sh` → no binary re-download, `cmp -s` no-op on config, no error noise.
  • Alias: `source ~/.zshrc && command -v oc` resolves to opencode.
  • Healthcheck: `./scripts/healthcheck.sh` includes section 10/11 OpenCode (3 checks: binary, config, schema).
  • Bats: `~/.local/bin/bats tests/opencode.bats` → 27/27.
  • Manual: launch `oc` → `/connect` → select OpenCode Go → paste API key → `/models` shows only DeepSeek V4 Pro + Kimi K2.6 under opencode-go provider.
  • AGENTS.md: confirm OpenCode reads it at repo root on first launch (no fallback to vendored prompt).

References

  • Spec: `specs/AI-011-opencode-bootstrap/` (proposal, tasks, verification)
  • ADR: `adr-009-multi-agent-runtime` (vault)
  • Pattern: `pattern-setup-script-idempotence` (vault)
  • Runbook: `10_projects/dotfiles/40-runbooks/guide-opencode-go-setup.md` (vault)
  • Closes: AI-011, AI-013

Follow-ups (not in this PR)

  • PR2 — Aider sunset + amend ADR-009 status proposedaccepted.
  • Hive MCP lock-file (separate repo) for safe parallel oc + claude on the same repo.
  • A/B comparison Kimi K2.6 vs DeepSeek V4 Pro after first month of real use.

Adds OpenCode as a secondary AI coding agent alongside Claude Code, with
the Go subscription as the primary provider (catalog-restricted to prevent
accidental PAYG billing) and OpenRouter as an env-detected fallback.
Aider stays in this PR (coexistence); sunset is PR2.

Folds AI-013 (copilot-instructions-refresh): canonical agent instructions
migrate to AGENTS.md at repo root (read natively by OpenCode and other
agents.md-aware tools per ADR-009). CLAUDE.md, GEMINI.md, and both
copilot-instructions.md files shrink to pointer-style files retaining only
agent-specific extensions.

Bug fixes en passant (zero-debt rule):
- Unresolved template placeholder 'the knowledge base (...)' in both
  copilot-instructions.md files.
- Wrong path %USERPROFILE%\Apps\knowledge\ -> Projects\knowledge in the
  same files.

Idempotence per pattern-setup-script-idempotence: command -v gate before
install, cmp -s reconcile-not-skip on config deploy, post-deploy
assertion, no silenced errors introduced.

Tests: 27 new in tests/opencode.bats (relational, not presence-only).
healthcheck.sh extended with section 10/11 (OpenCode binary + config +
schema). All 493 tests pass.

Spec: specs/AI-011-opencode-bootstrap/
Vault runbook: 10_projects/dotfiles/40-runbooks/guide-opencode-go-setup.md
…igration

The integration test asserted "CORE PRINCIPLE" appears in deployed
~/.claude/CLAUDE.md and ~/.gemini/GEMINI.md. That string was in the
canonical Neural Hive Protocol section, which now lives in AGENTS.md
(the per-agent files are pointers).

Switch both the post-deploy verify in setup-linux.sh and the integration
test assertions to grep for 'First, read `AGENTS.md`' — the canonical
pointer header present in both shrunk files.

Detected by integration CI on PR #34.
@mlorentedev mlorentedev merged commit bb967d6 into main May 17, 2026
5 checks passed
mlorentedev added a commit that referenced this pull request May 21, 2026
)

Mirror of AI-011 (Linux bootstrap, PRs #34/#36/#37, 2026-05-16) on the
Windows side. The Linux path uses `curl -fsSL https://opencode.ai/install
| bash`; empirical probe 2026-05-21 against winget revealed
`SST.opencode` (v1.15.6) is published natively, user-scope installable,
PATH handled by winget itself. That is substantially cleaner than the
original AI-014 backlog entry's "admin-conditional curl-bash equivalent
or npm install" hypothesis and reduces this spec from ~150 LOC of
admin-detection logic to ~75 LOC of straight mirror.

Changes (3 production files, 1 test file, ~98 LOC):

1. setup-windows.ps1 section 1c: append `SST.opencode` to the existing
   `$tools` winget array. Idempotent via the foreach's per-tool
   `Get-Command opencode` guard. Inherits the section's post-loop
   PATH refresh.

2. setup-windows.ps1 new section 2d (after 2c Obsidian CLI):
     (a) Deploy `ai/opencode/opencode.jsonc` to
         `%USERPROFILE%\.config\opencode\opencode.jsonc` using SHA256
         byte-equality test before copy (reconcile-not-skip,
         mirror of setup-linux.sh:415-428's cmp -s).
     (b) Sync `ai/opencode/commands/*.md` to
         `%USERPROFILE%\.config\opencode\commands\` with add/skip/
         remove-orphan counters identical to setup-linux.sh:430-465.

3. scripts/healthcheck.ps1 sec 10/12: drop the "AI-014 pending"
   parenthetical from SKIP messages. The PASS path (Test-Command
   'opencode' true + jsonc deployed) was already wired; this just
   removes the now-obsolete pointer.

4. tests/setup-windows.bats: 3 new asserts locking the SST.opencode
   entry, the SHA256-guarded jsonc deploy, and the orphan-removal in
   the commands sync.

Spec at specs/AI-014-opencode-windows-bootstrap/. Production diff 74
LOC (>= 50 threshold) so spec-gate enforces a spec folder, satisfied.

Empirical probe transcript captured in verification.md:
  - winget search opencode -> SST.opencode v1.15.6 user-installable
  - opencode.ai/install.ps1 -> 404 (no PowerShell installer upstream)
  - npm opencode-ai -> v1.15.7 (fallback channel, not chosen)

Coexistence constraint with Claude Code (Hive MCP write lock race) is
documented in 40-runbooks/guide-opencode-go-setup.md; that runbook is
OS-agnostic for /connect / PAYG-guardrail / troubleshooting and a small
Windows install delta gets folded post-merge.

Lesson candidate (post-merge):
  "When porting a Linux feature to Windows, probe the native package
   manager (winget) FIRST before assuming the Linux install path is
   the only option. The cleaner channel often exists but is invisible
   to a Linux-first design."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant